<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>芯片测试数据可视化</title>
  <!-- 引入 Chart.js 库 -->
  <script src="./src/chart.js"></script>
  <!-- 引入 Tailwind CSS -->
  <link rel="stylesheet" href="./src/output.css">
  <!-- 引入 Font Awesome -->
  <link href="./src/fontawesome-free-7.0.0-web/css/all.min.css" rel="stylesheet">


  <style>
    .content-auto {
      content-visibility: auto;
    }

    .card-shadow {
      box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
    }


    .sortable-header {
      cursor: pointer;
      transition: all 0.3s ease;
      position: relative;
      padding-right: 25px !important;
    }

    .sortable-header:hover {
      background-color: #f3f4f6;
    }

    .sort-indicator {
      position: absolute;
      right: 8px;
      top: 50%;
      transform: translateY(-50%);
      font-size: 12px;
    }

    .sort-asc .sort-indicator::after {
      content: "↑";
      color: #3b82f6;
    }

    .sort-desc .sort-indicator::after {
      content: "↓";
      color: #3b82f6;
    }

    .pagination-btn {
      @apply px-3 py-1 border border-gray-300 rounded-md text-sm font-medium text-gray-700 hover:bg-gray-50;
    }

    .pagination-btn-active {
      @apply bg-primary text-white border-primary;
    }

    .positive-change {
      color: #10b981;
    }

    .negative-change {
      color: #ef4444;
    }
  </style>
</head>

<body class="bg-gray-50 font-inter">
  <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
    <!-- 页面标题 -->
    <header class="mb-8 text-center">
      <h1 class="text-[clamp(1.8rem,4vw,2.5rem)] font-bold text-neutral-dark mb-2">芯片测试数据可视化工具</h1>
      <p class="text-gray-600 max-w-2xl mx-auto">上传不同时间段的芯片测试数据，选择参数和芯片 ID，查看测试数据变化趋势</p>
    </header>

    <!-- 上传区域 -->
    <div class="bg-white rounded-xl p-6 mb-8 card-shadow">
      <h2 class="text-xl font-bold text-neutral-dark mb-4 flex items-center">
        <i class="fas fa-upload text-primary mr-2"></i>数据上传
      </h2>
      <div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-4">
        <div class="upload-section">
          <button id="upload0h"
            class="bg-primary hover:bg-secondary text-white font-bold py-2 px-4 rounded transition-all duration-300 transform hover:scale-105 w-full justify-center">
            <i class="fa fa-clock-o"></i> 0 小时数据
          </button>
          <div id="status0h" class="mt-2 text-sm text-gray-500 text-center"></div>
        </div>
        <div class="upload-section">
          <button id="upload168h"
            class="bg-primary hover:bg-secondary text-white font-bold py-2 px-4 rounded transition-all duration-300 transform hover:scale-105 w-full justify-center">
            <i class="fa fa-clock-o"></i> 168 小时数据
          </button>
          <div id="status168h" class="mt-2 text-sm text-gray-500 text-center"></div>
        </div>
        <div class="upload-section">
          <button id="upload500h"
            class="bg-primary hover:bg-secondary text-white font-bold py-2 px-4 rounded transition-all duration-300 transform hover:scale-105 w-full justify-center">
            <i class="fa fa-clock-o"></i> 500 小时数据
          </button>
          <div id="status500h" class="mt-2 text-sm text-gray-500 text-center"></div>
        </div>
        <div class="upload-section">
          <button id="upload1000h"
            class="bg-primary hover:bg-secondary text-white font-bold py-2 px-4 rounded transition-all duration-300 transform hover:scale-105 w-full justify-center">
            <i class="fa fa-clock-o"></i> 1000 小时数据
          </button>
          <div id="status1000h" class="mt-2 text-sm text-gray-500 text-center"></div>
        </div>
      </div>
    </div>

    <!-- 筛选区域 -->
    <div class="bg-white rounded-xl p-6 mb-8 card-shadow">
      <h2 class="text-xl font-bold text-neutral-dark mb-4 flex items-center">
        <i class="fa fa-filter text-primary mr-2"></i>数据筛选
      </h2>
      <div class="grid grid-cols-1 md:grid-cols-2 gap-6">
        <div>
          <label for="parameterSelect" class="block text-sm font-medium text-gray-700 mb-1">选择参数</label>
          <select id="parameterSelect"
            class="block w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-primary focus:border-primary transition-all duration-300">
            <option value="">请选择参数</option>
          </select>
        </div>
        <div>
          <div class="flex justify-between items-center mb-2">
            <label class="block text-sm font-medium text-gray-700">每页显示数量</label>
            <select id="pageSizeSelect"
              class="block w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-primary focus:border-primary transition-all duration-300 w-24">
              <option value="10">10条</option>
              <option value="20">20条</option>
              <option value="50">50条</option>
              <option value="100">100条</option>
            </select>
          </div>
        </div>
        <div>
          <label for="searchInput" class="block text-sm font-medium text-gray-700 mb-1">筛选芯片 ID</label>
          <input type="text" id="searchInput"
            class="block w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-primary focus:border-primary transition-all duration-300"
            placeholder="输入芯片 ID 关键字">
        </div>
      </div>
    </div>

    <!-- 表格区域 -->
    <div class="bg-white rounded-xl p-6 mb-8 card-shadow overflow-x-auto">
      <div class="flex justify-between items-center mb-4">
        <h2 class="text-xl font-bold text-gray-800 flex items-center">
          <i class="fa fa-table text-blue-500 mr-2"></i>数据表格
        </h2>
        <div class="text-sm text-gray-500">
          <span>排序: </span>
          <span id="currentSortInfo" class="font-medium text-blue-600">未排序</span>
        </div>
      </div>
      <div class="overflow-x-auto">
        <table id="dataTable" class="min-w-full divide-y divide-gray-200">
          <thead>
            <tr>
              <th rowspan="2"
                class="px-6 py-3 bg-gray-50 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
                <div class="flex items-center">
                  <input type="checkbox" id="selectAllTable"
                    class="h-4 w-4 text-blue-500 focus:ring-blue-500 border-gray-300 rounded">
                  <span class="ml-2">选择</span>
                </div>
              </th>
              <th rowspan="2" data-sort="id" data-sort-type="number"
                class="sortable-header px-6 py-3 bg-gray-50 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
                芯片 ID
                <span class="sort-indicator"></span>
              </th>
              <th rowspan="2" data-sort="0h" data-sort-type="number"
                class="sortable-header px-6 py-3 bg-gray-50 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
                0 小时数据
                <span class="sort-indicator"></span>
              </th>
              <th colspan="4"
                class="px-6 py-3 bg-gray-100 text-center text-xs font-medium text-gray-500 uppercase tracking-wider">168
                小时数据</th>
              <th colspan="4"
                class="px-6 py-3 bg-gray-100 text-center text-xs font-medium text-gray-500 uppercase tracking-wider">500
                小时数据</th>
              <th colspan="4"
                class="px-6 py-3 bg-gray-100 text-center text-xs font-medium text-gray-500 uppercase tracking-wider">
                1000 小时数据</th>
            </tr>
            <tr>
              <th data-sort="168h_raw" data-sort-type="number"
                class="sortable-header px-6 py-3 bg-gray-50 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
                168h 数据
                <span class="sort-indicator"></span>
              </th>
              <th data-sort="168h_change" data-sort-type="number"
                class="sortable-header px-6 py-3 bg-gray-50 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
                相对0h变化量
                <span class="sort-indicator"></span>
              </th>
              <th data-sort="168h_rate" data-sort-type="number"
                class="sortable-header px-6 py-3 bg-gray-50 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
                相对0h变化率
                <span class="sort-indicator"></span>
              </th>
              <th data-sort="168h_prev_rate" data-sort-type="number"
                class="sortable-header px-6 py-3 bg-gray-50 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
                相对前次变化率
                <span class="sort-indicator"></span>
              </th>

              <th data-sort="500h_raw" data-sort-type="number"
                class="sortable-header px-6 py-3 bg-gray-50 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
                500h 数据
                <span class="sort-indicator"></span>
              </th>
              <th data-sort="500h_change" data-sort-type="number"
                class="sortable-header px-6 py-3 bg-gray-50 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
                相对0h变化量
                <span class="sort-indicator"></span>
              </th>
              <th data-sort="500h_rate" data-sort-type="number"
                class="sortable-header px-6 py-3 bg-gray-50 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
                相对0h变化率
                <span class="sort-indicator"></span>
              </th>
              <th data-sort="500h_prev_rate" data-sort-type="number"
                class="sortable-header px-6 py-3 bg-gray-50 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
                相对168h 变化率
                <span class="sort-indicator"></span>
              </th>

              <th data-sort="1000h_raw" data-sort-type="number"
                class="sortable-header px-6 py-3 bg-gray-50 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
                1000h 数据
                <span class="sort-indicator"></span>
              </th>
              <th data-sort="1000h_change" data-sort-type="number"
                class="sortable-header px-6 py-3 bg-gray-50 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
                相对0h变化量
                <span class="sort-indicator"></span>
              </th>
              <th data-sort="1000h_rate" data-sort-type="number"
                class="sortable-header px-6 py-3 bg-gray-50 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
                相对0h变化率
                <span class="sort-indicator"></span>
              </th>
              <th data-sort="1000h_prev_rate" data-sort-type="number"
                class="sortable-header px-6 py-3 bg-gray-50 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
                相对500h变化率
                <span class="sort-indicator"></span>
              </th>
            </tr>
          </thead>
          <tbody id="dataTableBody" class="bg-white divide-y divide-gray-200">
            <tr>
              <td colspan="16" class="px-6 py-10 text-center text-gray-500">请上传数据</td>
            </tr>
          </tbody>
        </table>
      </div>
      <!-- 分页控制 -->
      <div class="flex items-center justify-between mt-4">
        <div class="text-sm text-gray-700">
          <span id="paginationInfo">显示 0 到 0 条，共 0 条记录</span>
        </div>
        <div class="flex items-center space-x-1">
          <button id="prevPage" class="pagination-btn" disabled>上一页</button>
          <div id="paginationControls" class="flex items-center space-x-1">
            <!-- 分页按钮将在这里动态生成 -->
          </div>
          <button id="nextPage" class="pagination-btn" disabled>下一页</button>
        </div>
      </div>
    </div>

    <!-- 图表区域 -->
    <div class="bg-white rounded-xl p-6 card-shadow">
      <h2 class="text-xl font-bold text-gray-800 mb-4 flex items-center">
        <i class="fa fa-line-chart text-blue-500 mr-2"></i>数据可视化
      </h2>
      <div class="h-[400px]">
        <canvas id="myChart"></canvas>
      </div>
    </div>
  </div>

  <script>
    // 存储四个时间段的数据
    const dataByTime = {
      '0h': null,
      '168h': null,
      '500h': null,
      '1000h': null
    };

    // 存储所有芯片ID
    let allChipIds = new Set();

    // 存储选中的芯片ID
    let selectedChipIds = new Set();

    // 当前选择的参数
    let selectedParameter = '';

    // 存储所有参数
    let allParameters = new Set();

    // 分页相关变量
    let currentPage = 1;
    let pageSize = 10;
    let totalPages = 1;

    // 排序相关变量
    let sortColumn = null;
    let sortDirection = 'asc'; // 'asc' or 'desc'
    let sortType = 'number'; // 'number' or 'string'

    // 获取DOM元素
    const uploadButtons = {
      '0h': document.getElementById('upload0h'),
      '168h': document.getElementById('upload168h'),
      '500h': document.getElementById('upload500h'),
      '1000h': document.getElementById('upload1000h')
    };

    const statusElements = {
      '0h': document.getElementById('status0h'),
      '168h': document.getElementById('status168h'),
      '500h': document.getElementById('status500h'),
      '1000h': document.getElementById('status1000h')
    };

    const parameterSelect = document.getElementById('parameterSelect');
    const pageSizeSelect = document.getElementById('pageSizeSelect');
    const dataTableBody = document.getElementById('dataTableBody');
    const ctx = document.getElementById('myChart').getContext('2d');
    const prevPageBtn = document.getElementById('prevPage');
    const nextPageBtn = document.getElementById('nextPage');
    const paginationControls = document.getElementById('paginationControls');
    const paginationInfo = document.getElementById('paginationInfo');
    const selectAllTableCheckbox = document.getElementById('selectAllTable');
    const searchInput = document.getElementById('searchInput');
    const currentSortInfo = document.getElementById('currentSortInfo');

    // 图表实例
    let myChart;

    // 初始化
    init();

    function init() {
      // 为上传按钮添加事件监听器
      for (const [time, button] of Object.entries(uploadButtons)) {
        button.addEventListener('click', () => handleUpload(time));
      }

      // 为参数选择下拉框添加事件监听器
      parameterSelect.addEventListener('change', (e) => {
        selectedParameter = e.target.value;
        currentPage = 1; // 重置到第一页
        updateTableAndChart();
      });

      // 为每页显示数量下拉框添加事件监听器
      pageSizeSelect.addEventListener('change', (e) => {
        pageSize = parseInt(e.target.value);
        currentPage = 1; // 重置到第一页
        updateTableAndChart();
      });

      // 为全选复选框添加事件监听器
      selectAllTableCheckbox.addEventListener('change', (e) => {
        const checkboxes = document.querySelectorAll('#dataTableBody input[type="checkbox"]');
        checkboxes.forEach(checkbox => {
          checkbox.checked = e.target.checked;
          const chipId = checkbox.value;
          if (e.target.checked) {
            selectedChipIds.add(chipId);
          } else {
            selectedChipIds.delete(chipId);
          }
        });
        updateChart();
      });

      // 为上一页按钮添加事件监听器
      prevPageBtn.addEventListener('click', () => {
        if (currentPage > 1) {
          currentPage--;
          updateTable();
        }
      });

      // 为下一页按钮添加事件监听器
      nextPageBtn.addEventListener('click', () => {
        if (currentPage < totalPages) {
          currentPage++;
          updateTable();
        }
      });

      // 为搜索输入框添加事件监听器
      searchInput.addEventListener('input', () => {
        currentPage = 1; // 重置到第一页
        updateTableAndChart();
      });

      // 为排序表头添加事件监听器
      const sortableHeaders = document.querySelectorAll('.sortable-header');
      sortableHeaders.forEach(header => {
        header.addEventListener('click', (e) => {
          const column = e.currentTarget.dataset.sort;
          const type = e.currentTarget.dataset.sortType;

          // 如果点击的是当前排序列，则切换方向
          if (sortColumn === column) {
            sortDirection = sortDirection === 'asc' ? 'desc' : 'asc';
          } else {
            // 否则设置新的排序列和方向
            sortColumn = column;
            sortDirection = 'asc';
            sortType = type;
          }

          // 更新排序指示器
          updateSortIndicators();

          // 更新表格
          currentPage = 1;
          updateTableAndChart();
        });
      });

      // 初始化参数选择
      renderParameterSelect();
    }



    // 处理文件上传
    function handleUpload(time) {
      const input = document.createElement('input');
      input.type = 'file';
      input.accept = '.json';
      input.addEventListener('change', async (event) => {
        const file = event.target.files[0];
        if (file) {
          try {
            updateStatus(time, '上传中...', 'text-blue-500');
            const reader = new FileReader();
            reader.onload = (e) => {
              try {
                const data = JSON.parse(e.target.result);
                dataByTime[time] = data;
                updateStatus(time, `已上传 ${data.length} 条记录`, 'text-green-500');

                // 更新芯片ID集合
                updateChipIds(data);

                // 更新参数集合
                updateParameters(data);

                // 更新界面
                currentPage = 1; // 重置到第一页
                updateTableAndChart();
              } catch (error) {
                updateStatus(time, '解析JSON失败', 'text-red-500');
                console.error('解析JSON时出错:', error);
              }
            };
            reader.readAsText(file);
          } catch (error) {
            updateStatus(time, '上传失败', 'text-red-500');
            console.error('读取文件时出错:', error);
          }
        }
      });
      input.click();
    }

    // 更新上传状态
    function updateStatus(time, message, className) {
      const statusElement = statusElements[time];
      statusElement.textContent = message;
      statusElement.className = `mt-2 text-sm ${className} text-center`;
    }

    // 更新芯片ID集合
    function updateChipIds(data) {
      data.forEach(item => {
        if (item.PART_ID) {
          allChipIds.add(item.PART_ID);
        }
      });
    }

    // 更新参数集合
    function updateParameters(data) {
      data.forEach(item => {
        for (const key in item) {
          // 排除PART_ID，因为它用于芯片标识，不是测试参数
          if (key !== 'PART_ID') {
            allParameters.add(key);
          }
        }
      });
      renderParameterSelect();
    }

    // 渲染参数选择下拉框
    function renderParameterSelect() {
      // 清空现有选项
      parameterSelect.innerHTML = '';

      // 添加默认选项
      const defaultOption = document.createElement('option');
      defaultOption.value = '';
      defaultOption.textContent = '请选择参数';
      parameterSelect.appendChild(defaultOption);

      // 添加所有参数选项
      allParameters.forEach(param => {
        const option = document.createElement('option');
        option.value = param;
        option.textContent = param;
        parameterSelect.appendChild(option);
      });

      // 如果有参数且没有选择，默认选择第一个参数
      if (allParameters.size > 0 && !selectedParameter) {
        parameterSelect.value = Array.from(allParameters)[0];
        selectedParameter = parameterSelect.value;
        updateTableAndChart();
      } else if (selectedParameter) {
        parameterSelect.value = selectedParameter;
      }
    }

    // 更新表格和图表
    function updateTableAndChart() {
      // 按芯片 ID 分组数据
      const groupedData = groupDataByChipId();

      // 更新表格
      updateTable(groupedData);

      // 更新图表
      updateChart(groupedData);
    }

    // 按芯片ID分组数据
    function groupDataByChipId() {
      const groupedData = {};

      for (const [time, data] of Object.entries(dataByTime)) {
        if (data) {
          for (const item of data) {
            const partId = item.PART_ID;
            if (!partId) continue;

            if (!groupedData[partId]) {
              groupedData[partId] = {};
            }

            groupedData[partId][time] = item;
          }
        }
      }

      return groupedData;
    }

    // 更新排序指示器
    function updateSortIndicators() {
      // 移除所有排序类
      const sortableHeaders = document.querySelectorAll('.sortable-header');
      sortableHeaders.forEach(header => {
        header.classList.remove('sort-asc', 'sort-desc');
      });

      // 更新当前排序信息
      if (sortColumn) {
        const header = document.querySelector(`.sortable-header[data-sort="${sortColumn}"]`);
        if (header) {
          header.classList.add(`sort-${sortDirection}`);
          const columnName = header.textContent.trim();
          currentSortInfo.textContent = `${columnName} (${sortDirection === 'asc' ? '升序' : '降序'})`;
        }
      } else {
        currentSortInfo.textContent = '未排序';
      }
    }

    // 更新表格
    function updateTable(groupedData = groupDataByChipId()) {
      dataTableBody.innerHTML = '';

      if (Object.keys(groupedData).length === 0) {
        dataTableBody.innerHTML = `
          <tr>
            <td colspan="16" class="px-6 py-10 text-center text-gray-500">请上传数据</td>
          </tr>
        `;
        updatePagination(0);
        return;
      }

      if (!selectedParameter) {
        dataTableBody.innerHTML = `
          <tr>
            <td colspan="16" class="px-6 py-10 text-center text-gray-500">请选择参数</td>
          </tr>
        `;
        updatePagination(0);
        return;
      }

      // 获取所有芯片ID
      let allChipIds = Object.keys(groupedData);

      // 根据搜索关键字筛选芯片ID
      const searchKeyword = searchInput.value.trim().toLowerCase();
      if (searchKeyword) {
        allChipIds = allChipIds.filter(chipId => chipId.toLowerCase().includes(searchKeyword));
      }

      // 排序
      if (sortColumn) {
        allChipIds = sortChipIds(allChipIds, groupedData);
      }

      // 计算总页数
      totalPages = Math.ceil(allChipIds.length / pageSize);

      // 确保当前页码有效
      if (currentPage > totalPages) {
        currentPage = totalPages;
      }

      // 计算当前页要显示的芯片ID
      const startIndex = (currentPage - 1) * pageSize;
      const endIndex = Math.min(startIndex + pageSize, allChipIds.length);
      const chipIdsToDisplay = allChipIds.slice(startIndex, endIndex);

      // 更新分页信息
      updatePagination(allChipIds.length);

      if (chipIdsToDisplay.length === 0) {
        dataTableBody.innerHTML = `
          <tr>
            <td colspan="16" class="px-6 py-10 text-center text-gray-500">没有数据条目</td>
          </tr>
        `;
        return;
      }

      chipIdsToDisplay.forEach(partId => {
        if (!groupedData[partId]) return;

        const row = document.createElement('tr');
        row.className = 'hover:bg-gray-50 transition-colors';

        // 选择复选框单元格
        const checkboxCell = document.createElement('td');
        checkboxCell.className = 'px-6 py-4 whitespace-nowrap';

        const checkbox = document.createElement('input');
        checkbox.type = 'checkbox';
        checkbox.value = partId;
        checkbox.className = 'h-4 w-4 text-blue-500 focus:ring-blue-500 border-gray-300 rounded';
        checkbox.checked = selectedChipIds.has(partId);

        checkbox.addEventListener('change', (e) => {
          if (e.target.checked) {
            selectedChipIds.add(partId);
          } else {
            selectedChipIds.delete(partId);
          }
          updateChart();
        });

        checkboxCell.appendChild(checkbox);
        row.appendChild(checkboxCell);

        // 芯片ID单元格
        const idCell = document.createElement('td');
        idCell.className = 'px-6 py-4 whitespace-nowrap text-sm font-medium text-gray-900';
        idCell.textContent = partId;
        row.appendChild(idCell);

        // 获取0h数据
        const timePoints = ['0h', '168h', '500h', '1000h'];
        const values = {};

        timePoints.forEach(time => {
          const data = groupedData[partId][time];
          if (data && data[selectedParameter] !== undefined) {
            const value = parseFloat(data[selectedParameter]);
            values[time] = isNaN(value) ? null : value;
          } else {
            values[time] = null;
          }
        });

        // 添加0h数据单元格
        const zeroHourCell = document.createElement('td');
        zeroHourCell.className = 'px-6 py-4 whitespace-nowrap text-sm text-gray-500';
        zeroHourCell.textContent = values['0h'] !== null ? values['0h'].toFixed(4) : '无数据';
        row.appendChild(zeroHourCell);

        // 为每个时间段添加单元格（168h, 500h, 1000h）
        for (let i = 1; i < timePoints.length; i++) {
          const currentTime = timePoints[i];
          const previousTime = timePoints[i - 1];

          // 原始值单元格
          const valueCell = document.createElement('td');
          valueCell.className = 'px-6 py-4 whitespace-nowrap text-sm text-gray-500';
          valueCell.textContent = values[currentTime] !== null ? values[currentTime].toFixed(4) : '无数据';
          row.appendChild(valueCell);

          // 相对0h变化量单元格
          const changeFromZeroCell = document.createElement('td');
          changeFromZeroCell.className = 'px-6 py-4 whitespace-nowrap text-sm';

          if (values['0h'] !== null && values[currentTime] !== null) {
            const change = values[currentTime] - values['0h'];
            changeFromZeroCell.textContent = change.toFixed(4);
            changeFromZeroCell.className += change >= 0 ? ' text-green-600' : ' text-red-600';
          } else {
            changeFromZeroCell.textContent = '无数据';
          }
          row.appendChild(changeFromZeroCell);

          // 相对0h变化率单元格
          const rateFromZeroCell = document.createElement('td');
          rateFromZeroCell.className = 'px-6 py-4 whitespace-nowrap text-sm';

          if (values['0h'] !== null && values['0h'] !== 0 && values[currentTime] !== null) {
            const rate = (values[currentTime] - values['0h']) / values['0h'] * 100;
            rateFromZeroCell.textContent = `${rate.toFixed(2)}%`;
            rateFromZeroCell.className += rate >= 0 ? ' text-green-600' : ' text-red-600';
          } else {
            rateFromZeroCell.textContent = '无数据';
          }
          row.appendChild(rateFromZeroCell);

          // 相对前次变化率单元格
          const rateFromPreviousCell = document.createElement('td');
          rateFromPreviousCell.className = 'px-6 py-4 whitespace-nowrap text-sm';

          if (values[previousTime] !== null && values[previousTime] !== 0 && values[currentTime] !== null) {
            const rate = (values[currentTime] - values[previousTime]) / values[previousTime] * 100;
            rateFromPreviousCell.textContent = `${rate.toFixed(2)}%`;
            rateFromPreviousCell.className += rate >= 0 ? ' text-green-600' : ' text-red-600';
          } else {
            rateFromPreviousCell.textContent = '无数据';
          }
          row.appendChild(rateFromPreviousCell);
        }

        dataTableBody.appendChild(row);
      });

      // 更新全选复选框状态
      updateSelectAllCheckbox();

      // 更新排序指示器
      updateSortIndicators();
    }

    // 排序芯片ID
    function sortChipIds(chipIds, groupedData) {
      return [...chipIds].sort((a, b) => {
        const dataA = groupedData[a];
        const dataB = groupedData[b];

        let valueA, valueB;

        // 根据排序列获取值
        switch (sortColumn) {
          case 'id':
            valueA = a;
            valueB = b;
            break;
          case '0h':
            valueA = getValueForTime(dataA, '0h');
            valueB = getValueForTime(dataB, '0h');
            break;
          case '168h_raw':
            valueA = getValueForTime(dataA, '168h');
            valueB = getValueForTime(dataB, '168h');
            break;
          case '168h_change':
            valueA = getChangeValue(dataA, '168h');
            valueB = getChangeValue(dataB, '168h');
            break;
          case '168h_rate':
            valueA = getRateValue(dataA, '168h');
            valueB = getRateValue(dataB, '168h');
            break;
          case '168h_prev_rate':
            valueA = getPrevRateValue(dataA, '168h');
            valueB = getPrevRateValue(dataB, '168h');
            break;
          case '500h_raw':
            valueA = getValueForTime(dataA, '500h');
            valueB = getValueForTime(dataB, '500h');
            break;
          case '500h_change':
            valueA = getChangeValue(dataA, '500h');
            valueB = getChangeValue(dataB, '500h');
            break;
          case '500h_rate':
            valueA = getRateValue(dataA, '500h');
            valueB = getRateValue(dataB, '500h');
            break;
          case '500h_prev_rate':
            valueA = getPrevRateValue(dataA, '500h');
            valueB = getPrevRateValue(dataB, '500h');
            break;
          case '1000h_raw':
            valueA = getValueForTime(dataA, '1000h');
            valueB = getValueForTime(dataB, '1000h');
            break;
          case '1000h_change':
            valueA = getChangeValue(dataA, '1000h');
            valueB = getChangeValue(dataB, '1000h');
            break;
          case '1000h_rate':
            valueA = getRateValue(dataA, '1000h');
            valueB = getRateValue(dataB, '1000h');
            break;
          case '1000h_prev_rate':
            valueA = getPrevRateValue(dataA, '1000h');
            valueB = getPrevRateValue(dataB, '1000h');
            break;
          default:
            return 0;
        }

        // 处理空值
        if (valueA === null && valueB === null) return 0;
        if (valueA === null) return 1;
        if (valueB === null) return -1;

        // 排序
        //if (sortType === 'string') {
        //  return sortDirection === 'asc'
        //    ? valueA.localeCompare(valueB)
        //    : valueB.localeCompare(valueA);
        //} else {
        return sortDirection === 'asc'
          ? valueA - valueB
          : valueB - valueA;
        // }
      });
    }

    // 获取指定时间点的值
    function getValueForTime(data, time) {
      if (!data || !data[time] || !data[time][selectedParameter]) return null;
      return parseFloat(data[time][selectedParameter]);
    }

    // 获取变化量
    function getChangeValue(data, time) {
      if (!data || !data[time] || !data[time][selectedParameter] ||
        !data['0h'] || !data['0h'][selectedParameter]) return null;

      const currentValue = parseFloat(data[time][selectedParameter]);
      const zeroValue = parseFloat(data['0h'][selectedParameter]);
      return currentValue - zeroValue;
    }

    // 获取变化率
    function getRateValue(data, time) {
      if (!data || !data[time] || !data[time][selectedParameter] ||
        !data['0h'] || !data['0h'][selectedParameter]) return null;

      const currentValue = parseFloat(data[time][selectedParameter]);
      const zeroValue = parseFloat(data['0h'][selectedParameter]);
      if (zeroValue === 0) return null;
      return (currentValue - zeroValue) / zeroValue * 100;
    }

    // 获取相对前次变化率
    function getPrevRateValue(data, time) {
      let prevTime;
      if (time === '168h') prevTime = '0h';
      else if (time === '500h') prevTime = '168h';
      else if (time === '1000h') prevTime = '500h';
      else return null;

      if (!data || !data[time] || !data[time][selectedParameter] ||
        !data[prevTime] || !data[prevTime][selectedParameter]) return null;

      const currentValue = parseFloat(data[time][selectedParameter]);
      const prevValue = parseFloat(data[prevTime][selectedParameter]);
      if (prevValue === 0) return null;
      return (currentValue - prevValue) / prevValue * 100;
    }

    // 更新分页信息和控制
    function updatePagination(totalItems) {
      // 更新分页信息
      const startItem = (currentPage - 1) * pageSize + 1;
      const endItem = Math.min(currentPage * pageSize, totalItems);
      paginationInfo.textContent = `显示 ${startItem} 到 ${endItem} 条，共 ${totalItems} 条记录`;

      // 更新分页按钮
      paginationControls.innerHTML = '';

      // 计算要显示的页码范围
      let startPage = Math.max(1, currentPage - 2);
      let endPage = Math.min(totalPages, startPage + 4);

      if (endPage - startPage < 4 && startPage > 1) {
        startPage = Math.max(1, endPage - 4);
      }

      // 添加首页按钮
      if (startPage > 1) {
        addPageButton(1);
        if (startPage > 2) {
          addEllipsis();
        }
      }

      // 添加页码按钮
      for (let i = startPage; i <= endPage; i++) {
        addPageButton(i);
      }

      // 添加末页按钮
      if (endPage < totalPages) {
        if (endPage < totalPages - 1) {
          addEllipsis();
        }
        addPageButton(totalPages);
      }

      // 启用/禁用上一页和下一页按钮
      prevPageBtn.disabled = currentPage === 1;
      nextPageBtn.disabled = currentPage === totalPages;
    }

    // 添加分页按钮
    function addPageButton(pageNum) {
      const button = document.createElement('button');
      button.className = `pagination-btn ${currentPage === pageNum ? 'pagination-btn-active' : ''}`;
      button.textContent = pageNum;

      button.addEventListener('click', () => {
        currentPage = pageNum;
        updateTable();
      });

      paginationControls.appendChild(button);
    }

    // 添加省略号
    function addEllipsis() {
      const ellipsis = document.createElement('span');
      ellipsis.className = 'px-2 text-gray-700';
      ellipsis.textContent = '...';
      paginationControls.appendChild(ellipsis);
    }

    // 更新全选复选框状态
    function updateSelectAllCheckbox() {
      const checkboxes = document.querySelectorAll('#dataTableBody input[type="checkbox"]');
      const checkedCount = document.querySelectorAll('#dataTableBody input[type="checkbox"]:checked').length;

      // 如果所有可见的复选框都被选中，则全选复选框也被选中
      selectAllTableCheckbox.checked = checkboxes.length > 0 && checkedCount === checkboxes.length;
    }

    // 更新图表
    function updateChart(groupedData = groupDataByChipId()) {
      if (myChart) {
        myChart.destroy();
      }

      if (!selectedParameter) {
        return;
      }

      const times = ['0h', '168h', '500h', '1000h'];
      const timesInHours = [0, 168, 500, 1000];

      // 获取所有选中的芯片ID
      const chipIdsToDisplay = Array.from(selectedChipIds).filter(chipId => groupedData[chipId]);

      if (chipIdsToDisplay.length === 0) {
        return;
      }

      const datasets = [];

      chipIdsToDisplay.forEach(partId => {
        if (!groupedData[partId]) return;

        const chipData = groupedData[partId];
        // 创建包含X和Y值的数组，X为小时数，Y为参数值
        const dataPoints = times.map((time, index) => {
          const item = chipData[time];
          if (item && item[selectedParameter] !== undefined) {
            const value = parseFloat(item[selectedParameter]);
            return isNaN(value) ? null : { x: timesInHours[index], y: value };
          }
          return null;
        }).filter(point => point !== null); // 过滤掉空值

        // 只添加有数据的芯片
        if (dataPoints.length > 0) {
          const color = getRandomColor();
          datasets.push({
            label: `芯片 ${partId}`,
            data: dataPoints,
            borderColor: color,
            backgroundColor: getRandomColor(0.2),
            borderWidth: 2,
            pointRadius: 4,
            pointBackgroundColor: color,
            tension: 0.1,
            fill: false
          });
        }
      });

      // 如果没有有效的数据集，不绘制图表
      if (datasets.length === 0) {
        return;
      }

      myChart = new Chart(ctx, {
        type: 'line',
        data: {
          datasets: datasets
        },
        options: {
          responsive: true,
          maintainAspectRatio: false,
          plugins: {
            legend: {
              position: 'top',
              labels: {
                boxWidth: 12,
                usePointStyle: true,
                pointStyle: 'circle'
              }
            },
            tooltip: {
              mode: 'index',
              intersect: false,
              callbacks: {
                label: function (context) {
                  let label = context.dataset.label || '';
                  if (label) {
                    label += ': ';
                  }
                  if (context.parsed.y !== undefined) {
                    label += context.parsed.y.toFixed(4);
                  } else {
                    label += '无数据';
                  }
                  return label;
                }
              }
            }
          },
          scales: {
            x: {
              type: 'linear', // 使用线性轴，根据实际时间值进行缩放
              title: {
                display: true,
                text: '测试时间 (小时)',
                font: {
                  weight: 'bold'
                }
              },
              grid: {
                display: true
              },
              // 强制显示所有时间点的刻度
              ticks: {
                callback: function (value) {
                  // 确保只显示我们定义的时间点
                  if (timesInHours.includes(value)) {
                    return value;
                  }
                  return '';
                }
              }
            },
            y: {
              title: {
                display: true,
                text: selectedParameter,
                font: {
                  weight: 'bold'
                }
              },
              grid: {
                display: true
              }
            }
          },
          animation: {
            duration: 1000,
            easing: 'easeOutQuart'
          }
        }
      });
    }

    // 生成随机颜色
    function getRandomColor(alpha = 1) {
      const r = Math.floor(Math.random() * 256);
      const g = Math.floor(Math.random() * 256);
      const b = Math.floor(Math.random() * 256);
      return `rgba(${r}, ${g}, ${b}, ${alpha})`;
    }
  </script>
</body>

</html>